package com.meta.builder.freemarker;

import com.meta.builder.IMetaTemplate;
import com.meta.builder.freemarker.cls.ClassBuilder;
import com.meta.internal.Options;
import freemarker.template.Configuration;
import freemarker.template.Template;

import javax.lang.model.element.Element;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FreemarkerProcessor {
    private Configuration configuration;
    private Options options;
    private List<IMetaTemplate> templateList = new ArrayList<>() {{
        add(new ClassBuilder());
    }};

    public FreemarkerProcessor(Options options) {
        this.configuration = new Configuration(Configuration.VERSION_2_3_30);
        this.options = options;
        options.setFkConfig(configuration);
        this.processTemp(options);
    }

    /**
     * 模板加载
     *
     * @param options 配置项
     */
    private void processTemp(Options options) {
        Map<String, IMetaTemplate> templates = new HashMap<>();
        configuration.setClassForTemplateLoading(ClassBuilder.class, "template/");
        templateList.forEach(cls -> {
            templates.put(cls.getClass().getName(), cls);
        });
        configuration.clearTemplateCache();
        options.setTemplates(templates);
    }

    public boolean writeSource(IMetaTemplate templateModel, Element element) throws IOException {
        Map<String, Object> maps = templateModel.getParamMap();
        try {
            StringWriter writer = new StringWriter();
            Template template = templateModel.getTemplate();
            template.process(maps, writer);
            String clsContext = writer.toString();
            templateModel.writer(options.getProcessingEnv(), clsContext);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    protected Configuration getConfiguration() {
        return configuration;
    }

    protected void setConfiguration(Configuration configuration) {
        this.configuration = configuration;
    }
}